package com.jwgf.smarowindingmachine_unity.ui;

import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.fastjson.JSON;
import com.jwgf.adapter.DensityUtils;
import com.jwgf.adapter.MultiItemTypeAdapter;
import com.jwgf.decoration.SpaceItemDecoration;
import com.jwgf.group.Group;
import com.jwgf.itemviewdelegates.StatisticButtonAttr;
import com.jwgf.itemviewdelegates.StatisticButtonDelegate;
import com.jwgf.objectbox.GroupInfo;
import com.jwgf.objectbox.ShiftReport;
import com.jwgf.objectbox.SpindleParameter;
import com.jwgf.objectbox.StatisticRecord;
import com.jwgf.smarowindingmachine_unity.R;
import com.jwgf.smarowindingmachine_unity.logic.MachineParameterSharedPreference;
import com.jwgf.smarowindingmachine_unity.logic.Report;
import com.jwgf.smarowindingmachine_unity.logic.UnitUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;
import lecho.lib.hellocharts.gesture.ContainerScrollType;
import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.model.SliceValue;
import lecho.lib.hellocharts.view.PieChartView;

public class ProductionBadSpindleAnalysisView extends RelativeLayout {

    private TextView filterText;
    private ImageButton filterBtn;

    private TextView craftContent;

    private RecyclerView rv;
    private MultiItemTypeAdapter<Object> rvAdapter;
    private List efficiencyList;

    private PieChartData chartData;
    private PieChartView chartView;
    private TextView statisticInfo;

    private int filterSelected = 0;
    private String filterName;
    private int rvSelected = 0;

    private List<ShiftReport> reports;
    private List<StatisticRecord> statistics;
    private GroupInfo groupInfo;
    private List<Group> groups;
    private int groupCnt = 0;


    public ProductionBadSpindleAnalysisView(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.production_bad_spindle_analysis_view, this);
        initViews();
    }

    private void initViews() {
        filterText = findViewById(R.id.filter_text);
        filterBtn = findViewById(R.id.filter_btn);
        filterName = getResources().getString(R.string.machine);
        filterText.setText(getResources().getString(R.string.machine));
        filterBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Bundle bundle = new Bundle();
                ArrayList<String> list = new ArrayList<>();
                list.add(getResources().getString(R.string.machine));
                for (int i = 1; i <= groupCnt; ++i) {
                    list.add(getResources().getString(R.string.group) + i);
                }
                bundle.putStringArrayList(CustomSelectedDialog.ITEMS, list);
                CustomSelectedDialog dlg = new CustomSelectedDialog();
                dlg.setArguments(bundle);
                dlg.setCallback(new CustomSelectedDialog.Callback() {
                    @Override
                    public void onItemSelected(String text, int index) {
                        filterName = text;
                        filterText.setText(text);
                        filterSelected = index;
                        updateCraftContent(filterSelected);
                        updateRecycler(filterSelected);
                    }
                });
                dlg.show(((FragmentActivity) getContext()).getSupportFragmentManager(), "selected");
            }
        });
        craftContent = findViewById(R.id.craft_content);
        rv = findViewById(R.id.recycler_view);
        chartView = findViewById(R.id.pie_chart);
        chartView.setInteractive(true);
        chartView.setZoomEnabled(false);
        chartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
        statisticInfo = findViewById(R.id.statistic_info);

        efficiencyList = new ArrayList<>();
        rvAdapter = new MultiItemTypeAdapter<Object>(getContext(), efficiencyList);
        rvAdapter.addItemViewDelegate(new StatisticButtonDelegate(rvAdapter));
        rvAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
                if (position == -1) {
                    return;
                } else {
                    rvSelected = position;
                    for (Object o : rvAdapter.getDatas()) {
                        StatisticButtonAttr attr = (StatisticButtonAttr) o;
                        ((StatisticButtonAttr) o).setSelected(false);
                    }
                    ((StatisticButtonAttr) rvAdapter.getDatas().get(position)).setSelected(true);
                    rvAdapter.notifyDataSetChanged();
                    updateChart(rvSelected);
                }
            }

            @Override
            public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
                return false;
            }
        });
        GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 5);
        rv.setLayoutManager(layoutManager);
        rv.addItemDecoration(new SpaceItemDecoration(DensityUtils.dp2px(2), DensityUtils.dp2px(2)));
        rv.setAdapter(rvAdapter);


    }

    public void loadData(long time) {
        groupInfo = Report.getInstance().getGroupInfo(time);
        reports = Report.getInstance().getProduction(time);
        statistics = Report.getInstance().getStatistic(time);
    }

    public void setData() {
        //计算分组数和单锭数
        calcGroupCnt();

        //更新下拉框内容
        updateFilter();

        // 更新recyclerview内容
        updateRecycler(filterSelected);

        // 绘制柱状图
        updateChart(rvSelected);

    }

    public void calcGroupCnt() {
        groups = JSON.parseArray(groupInfo.groupInfo, Group.class);
        groupCnt = groups.size();
        int count = 0;
        for (Group group : groups) {
            count += group.getSpindles().size();
        }
    }

    public void updateFilter() {
        filterSelected = updateFilterSelected();
        if (filterSelected == 0) {
            filterText.setText(getResources().getString(R.string.machine));
        }
        updateCraftContent(filterSelected);
    }

    private int updateFilterSelected() {
        ArrayList<String> list = new ArrayList<>();
        list.add(getResources().getString(R.string.machine));
        for (int i = 1; i <= groupCnt; ++i) {
            list.add(getResources().getString(R.string.group) + i);
        }
        int selected = list.indexOf(filterName);
        if (selected == -1) {
            filterName = list.get(0);
            return 0;
        } else {
            return selected;
        }
    }

    private void updateCraftContent(int index) {

        if (groupCnt == 1) {
            Observable.create(new ObservableOnSubscribe<String>() {
                @Override
                public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                    List<SpindleParameter> parameters = JSON.parseArray(groupInfo.spindleParameters, SpindleParameter.class);
                    if (parameters != null && !parameters.isEmpty()) {
                        SpindleParameter parameter = parameters.get(0);
                        StringBuilder sb = new StringBuilder();
                        sb.append("批次:").append("\n").append(parameter.craftName).append("\n");
                        String[] countUnit = getResources().getStringArray(R.array.count_unit);
                        int i = Integer.valueOf(MachineParameterSharedPreference.getInstance().getValue(MachineParameterSharedPreference.SYSTEM_COUNT_UNIT, "0"));
                        sb.append("支数").append("(").append(countUnit[i]).append("):").append("\n").append(String.format("%.1f", UnitUtils.getUICount(Float.parseFloat(parameter.frame28DC)))).append("\n");
                        String spdUnit = getResources().getString(R.string.ss_speedUnit);
                        if (MachineParameterSharedPreference.getInstance().getValue(MachineParameterSharedPreference.SYSTEM_LENGTH_UNIT, "0").equals("1")) {
                            spdUnit = getResources().getString(R.string.behind_ymin);
                        }
                        sb.append("络纱速度").append("(").append(spdUnit).append("):").append("\n").append(UnitUtils.getUILength(parameter.frame20DB));
                        emitter.onNext(sb.toString());
                    } else {
                        emitter.onNext("");
                    }
                }
            })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<String>() {
                        @Override
                        public void accept(String s) throws Exception {
                            craftContent.setText(s);
                        }
                    });
        } else {
            if (index == 0) {
                craftContent.setText("");
            } else {
                Observable.create(new ObservableOnSubscribe<String>() {
                    @Override
                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                        List<SpindleParameter> parameters = JSON.parseArray(groupInfo.spindleParameters, SpindleParameter.class);
                        if (parameters != null) {
                            SpindleParameter parameter = parameters.get(index - 1);
                            StringBuilder sb = new StringBuilder();
                            sb.append("批次:").append("\n").append(parameter.craftName).append("\n");
                            String[] countUnit = getResources().getStringArray(R.array.count_unit);
                            int i = Integer.valueOf(MachineParameterSharedPreference.getInstance().getValue(MachineParameterSharedPreference.SYSTEM_COUNT_UNIT, "0"));
                            sb.append("支数").append("(").append(countUnit[i]).append("):").append("\n").append(String.format("%.1f", UnitUtils.getUICount(Float.parseFloat(parameter.frame28DC)))).append("\n");
                            String spdUnit = getResources().getString(R.string.ss_speedUnit);
                            if (MachineParameterSharedPreference.getInstance().getValue(MachineParameterSharedPreference.SYSTEM_LENGTH_UNIT, "0").equals("1")) {
                                spdUnit = getResources().getString(R.string.behind_ymin);
                            }
                            sb.append("络纱速度").append("(").append(spdUnit).append("):").append("\n").append(UnitUtils.getUILength(parameter.frame20DB));
                            emitter.onNext(sb.toString());
                        } else {
                            emitter.onNext("");
                        }
                    }
                })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<String>() {
                            @Override
                            public void accept(String s) throws Exception {
                                craftContent.setText(s);
                            }
                        });
            }

        }

    }

    public void updateRecycler(int index) {
        // all
        List<ShiftReport> subList = new ArrayList<>(reports.subList(groupCnt + 2, reports.size()));
        // group
        if (index > 0) {
            Group group = groups.get(index - 1);
            int startIndex = group.getStartSpindle() - 1;
            int endIndex = group.getEndSpindle();
            subList = subList.subList(startIndex, endIndex);
        }
        // sort
        Collections.sort(subList, new Comparator<ShiftReport>() {
            @Override
            public int compare(ShiftReport o1, ShiftReport o2) {
                if (o1.runEfficiency < o2.runEfficiency) {
                    return -1;
                } else {
                    return 1;
                }
            }
        });
        // clear
        efficiencyList.clear();
        // rebuild list
        String namePrefix = "sp";
        int maxCount = Math.min(subList.size(), 10);
        for (int i = 0; i < maxCount; ++i) {
            StatisticButtonAttr attr = new StatisticButtonAttr(
                    namePrefix + subList.get(i).type, Report.round(String.valueOf(subList.get(i).runEfficiency), 2));
            efficiencyList.add(attr);

        }
        if (rvSelected >= efficiencyList.size()) {
            rvSelected = 0;
        }
        ((StatisticButtonAttr) efficiencyList.get(rvSelected)).setSelected(true);

        rvAdapter.notifyDataSetChanged();
    }

    private void updateChart(int index) {
        // all
        List<ShiftReport> subShiftList = new ArrayList<>(reports.subList(groupCnt + 2, reports.size()));
        List<StatisticRecord> subStatisticList = new ArrayList<>(statistics.subList(groupCnt + 2, reports.size()));
        // group
        if (filterSelected > 0) {
            Group group = groups.get(filterSelected - 1);
            int startIndex = group.getStartSpindle() - 1;
            int endIndex = group.getEndSpindle();
            subShiftList = subShiftList.subList(startIndex, endIndex);
            subStatisticList = subStatisticList.subList(startIndex, endIndex);
        }
        // sort
        Collections.sort(subShiftList, new Comparator<ShiftReport>() {
            @Override
            public int compare(ShiftReport o1, ShiftReport o2) {
                if ((int) o1.runEfficiency < (int) o2.runEfficiency) {
                    return -1;
                } else if ((int) o1.runEfficiency == (int) o2.runEfficiency) {
                    return 0;
                } else {
                    return 1;
                }
            }
        });

        ShiftReport spindle = subShiftList.get(index);
        StatisticRecord record = null;
        // find alarm index
        for (int i = 0; i < subStatisticList.size(); ++i) {
            if (subStatisticList.get(i).type.equals(spindle.type)) {
                record = subStatisticList.get(i);
                break;
            }
        }
        if (record == null) {
            record = new StatisticRecord();
            record.redLightTime = 0;
            record.faultTime = 0;
            record.processTime = 0;
        }


        long totalTime = spindle.windingTime / 1000 + spindle.spliceTime / 1000
                + record.redLightTime + record.faultTime + record.processTime;
        String[] labels = {"络纱", "打结", "红灯", "故障", "工艺"};
        if(totalTime != 0) {
            int windingPercent = (int) (spindle.windingTime / 1000 * 100 / totalTime);
            int splicePercent = (int) (spindle.spliceTime / 1000 * 100 / totalTime);
            int redPercent = (int) (record.redLightTime * 100 / totalTime);
            int faultPercent = (int) (record.faultTime * 100 / totalTime);
            int processPercent = (int) (record.processTime * 100 / totalTime);

            List<SliceValue> values = new ArrayList<>();
            if (windingPercent != 0) {
                SliceValue sliceValue = new SliceValue(windingPercent, Color.rgb(112, 146, 190));
                sliceValue.setLabel(labels[0] + "\n" + windingPercent + "%");//设置label
                values.add(sliceValue);
            }
            if (splicePercent != 0) {
                SliceValue sliceValue = new SliceValue(splicePercent, Color.rgb(181, 181, 181));
                sliceValue.setLabel(labels[1] + "\n" + splicePercent + "%");//设置label
                values.add(sliceValue);
            }
            if (redPercent != 0) {
                SliceValue sliceValue = new SliceValue(redPercent, Color.rgb(240, 68, 77));
                sliceValue.setLabel(labels[2] + "\n" + redPercent + "%");//设置label
                values.add(sliceValue);
            }
            if (faultPercent != 0) {
                SliceValue sliceValue = new SliceValue(faultPercent, Color.rgb(184, 95, 184));
                sliceValue.setLabel(labels[3] + "\n" + faultPercent + "%");//设置label
                values.add(sliceValue);
            }
            if (processPercent != 0) {
                SliceValue sliceValue = new SliceValue(processPercent, Color.rgb(255, 201, 14));
                sliceValue.setLabel(labels[4] + "\n" + processPercent + "%");//设置label
                values.add(sliceValue);
            }

            chartData = new PieChartData(values);
            chartData.setHasLabels(true);
            chartData.setHasLabelsOutside(true); //外部标签
            chartData.setSlicesSpacing(4);

            chartView.setCircleFillRatio(0.8f); // 设置饼图大小比例
            chartView.setPieChartData(chartData);
        } else {
            chartData = new PieChartData();
            chartView.setPieChartData(chartData);
        }

        // html风格String
        StringBuilder sb = new StringBuilder();
        String winding = labels[0] + " : " + Report.getInstance().subSecToTime(spindle.windingTime / 1000);
        String splice = labels[1] + " : " + Report.getInstance().subSecToTime(spindle.spliceTime / 1000)
                + "&emsp;&emsp;" + spindle.spliceCount;
        String red = labels[2] + " : " + Report.getInstance().subSecToTime(record.redLightTime)
                + "&emsp;&emsp;" + (int) record.redLightCount;
        String fault = labels[3] + " : " + Report.getInstance().subSecToTime(record.faultTime)
                + "&emsp;&emsp;" + (int) record.faultCount;
        String process = labels[4] + " : " + Report.getInstance().subSecToTime(record.processTime)
                + "&emsp;&emsp;" + (int) record.processCount;
        sb.append(htmlFormat(winding, Color.rgb(112, 146, 190)));
        sb.append(htmlFormat(splice, Color.rgb(181, 181, 181)));
        sb.append(htmlFormat(red, Color.rgb(240, 68, 77)));
        sb.append(htmlFormat(fault, Color.rgb(184, 95, 184)));
        sb.append(htmlFormat(process, Color.rgb(255, 201, 14)));
        float eff = 0;
        if (filterSelected == 0) {
            eff = reports.get(1).runEfficiency;
        } else {
            eff = reports.get(2 + filterSelected - 1).runEfficiency;
        }
        sb.append("平均效率 : " + Report.round(String.valueOf(eff), 2));

        statisticInfo.setText(Html.fromHtml(sb.toString()));

    }

    private String htmlFormat(String string, int color) {
        String content = String.format("<font color='#%06x'>%s</font><br>", color & 0xffffff, string);
        return content;
    }

}
